/* ========================= */
/*    forms		             */
/* need: helper/mask.js      */
var HooForm = new Class({
    _elements: ['input', 'textarea', 'select'],
    
    options : {
	action: undefined,
	parentElement: undefined,
	waitingClass: undefined,
	method: undefined,

	onSetError: undefined,   //should return true;
	onClearError: undefined, //should return true;
	errorClass: undefined,
	errorClasses: undefined,
	errorPlaceClass: 'formError',
	errorPlaceClassEmpty: 'formErrorEmpty',
	errorPlaces: {},
	errorNotifyType: ['flash'], //'place', 'class', 'flash', 'alert'
	flashDuration: 1000,
	flashStyles: {'background-color': '#FF0000'},
	onComplete: undefined,
	onSuccess: undefined,
	onBeforeRequest: undefined
    },

    initialize : function(element, options) {
	this.element = element;
	if ($defined(options)) this.setOptions(options); //options = $merge(this.options, options);
	this.element.addEvents( {
		submit: this.onSubmit.bindWithEvent(this)
	});
	this.element.getElements('input[type=submit]').each(function(el) {
		/*el.addEvents({
			'click': element.submit.bindWithEvent(this)
		});*/
		//alert(element);
	});
    },

    setOptions: function (options) {
	this.options = $merge(this.options, options);
    },

    clearError: function(el) {
	if ($defined(el._errorSet) && el._errorSet) {
	    if (this.options.onClearError != undefined && !this.options.onClearError(el, this)) {
		return;
	    } else {
		if ($defined(el._errorPlace)) {
		    el._errorPlace.empty();
		    el._errorPlace.removeClass(this.options.errorPlaceClass);
		    el._errorPlace.addClass(this.options.errorPlaceClassEmpty);
		}
		if ($defined(el._errorClass)) {
		    el.removeClass(el._errorClass);
		}
	    }
	    el._errorSet = false;
	}
    },
	
    clearErrors: function () {
	this._elements.each(function (nm) {
	this.element.getElements(nm).each(function(el) {
	    this.clearError(el);
	}.bind(this));
	}.bind(this));
    },
	
    setError: function (el, text) {
	if (this.options.onSetError != undefined && !this.options.onSetError(el, text, this)) return true;
	var name = $defined(el.id) && el.id!=''?el.id:($defined(el.name) && el.name!=''?el.name:'element');
	/* set error place */
	var use = this.options.errorNotifyType.toString().indexOf('place')!==-1;
	if (use && !$defined(el._errorPlace)) {
	    if ($defined(this.options.errorPlaces[name])) {
	        el._errorPlace = $(this.options.errorPlaces[name]);
	    } else {
	        el._errorPlace = new Element('div').injectAfter(el);
	    }
	}
	if (use) {
	    el._errorPlace.removeClass(this.options.errorPlaceClassEmpty);
	    el._errorPlace.set('html', text);
	    el._errorPlace.addClass(this.options.errorPlaceClass);
	}
	/* set error class */
	use = this.options.errorNotifyType.toString().indexOf('class')!==-1;
	if (use && !$defined(el._errorClass)) {
		if (this.options.errorClasses!=undefined && $defined(this.options.errorClasses[name])) {
			el._errorClass = this.options.errorClasses[name];
		} else {
			el._errorClass = this.options.errorClass;
		}
	}
	if (use) {
		el.addClass(el._errorClass);
	}
	/* flash */
	use = this.options.errorNotifyType.toString().indexOf('flash')!==-1;
	if (use && !$defined(el._errorFx)) {
		el._errorFx = new Fx.Morph(el, {duration: this.options.flashDuration, transition: Fx.Transitions.Sine.easeOut});
	}
	if (use) {
	    if (!$defined(el._errorFxTo)) {
		    el._errorFxTo = {};
		    for (var i in this.options.flashStyles) {
			el._errorFxTo[i] = el.getStyle(i);
		    }
	    }
	    el._errorFx.cancel();
	    el._errorFx.set(this.options.flashStyles);
	    el._errorFx.start(el._errorFxTo);
	}

	/* alert */
	use = this.options.errorNotifyType.toString().indexOf('alert')!==-1;
	if (use && $defined(HooAlert)) {
	    if (text) HooAlert.show(text);
	}

	el._errorSet = true;
	return true;
    },
	
    setValue: function (el, value) {
	if ((el.type=="radio" || el.type=="checkebox") && el.value == value) {
	    el.checked = (!value || value=='false')?false:true;
	} else if (el.type=='select') {
//TODO: make select set value available
	} else {
	    el.value = value;
	    //el.fireEvent('keydown');
	    el.fireEvent('keyup');
	}
    },

    onSubmit : function() {
	if (this.options.action == undefined) {
	    if (!$defined(this.element.action)) return false;
	    this.options.action = this.element.action;
	}
	if (this.options.parentElement == undefined) {
	    this.options.parentElement = this.element;
	    //this.options.parentElement = this.element.getParent();
	}
	this.options.parentElement.HooMaskSet(this.options.waitingClass);
	//this.clearErrors();
	if (this.options.action == undefined) this.options.action = this.element.action;
	if (this.options.method == undefined) {
		this.options.method = !$defined(this.element.method)?'post':this.element.method;
	}
	this._elements.each(function (nm) {
	    this.element.getElements(nm).each(function(el) {if ($defined(el._HooTip)) el._HooTip.onFocus(true);});
	}.bind(this));
	if (this.options.onBeforeRequest == undefined || this.options.onBeforeRequest(this)) {
	    this.element.set('send', {
		url: this.options.action,
		onSuccess: function (r1, r2, r3, r4) {
		r1 = JSON.decode(r1);
		this._elements.each(function(nm) {
		this.element.getElements(nm).each(function(el) {if ($defined(el._HooTip)) el._HooTip.onBlur(true);});
		}.bind(this));
		if (this.options.onComplete != undefined && !this.options.onComplete(r1, this)) return true;
		if (r1.status == 'ok') {
		    this.clearErrors();
		    this.options.parentElement.HooMaskRemove();
		    if (this.options.onSuccess != undefined) this.options.onSuccess(r1, this);
		    if ($defined(r1.reset) || r1.reset == true) {
			    this.element.reset();
		    } else {
			this._elements.each(function (nm) {
			this.element.getElements(nm).each(function(el) {
			    var name = $defined(el.id) && el.id!=''?el.id:($defined(el.name) && el.name!=''?el.name:'element');
			    if ($defined(r1.values) && $defined(r1.values[name])) {
				this.setValue(el, r1.values[name]);
			    }
			}.bind(this))
			}.bind(this));
		    }
		} else {
		    this._elements.each(function (nm) {
		    this.element.getElements(nm).each(function(el) {
			var name = $defined(el.id) && el.id!=''?el.id:($defined(el.name) && el.name!=''?el.name:'element');
			if ($defined(r1.errors) && $defined(r1.errors[name])) {
			    this.setError(el, r1.errors[name]);
			} else {
			    this.clearError(el);
			}
			if ($defined(r1.values) && $defined(r1.values[name])) {
			    this.setValue(el, r1.values[name]);
			}
		    }.bind(this))
		    }.bind(this));
		    if ($defined(r1.error)) this.setError(this.element, r1.error);
		    else this.clearError(this.element);
		    this.options.parentElement.HooMaskRemove();
		}
		return false;
	}.bind(this)
	});
	this.element.send();
    }
    this._elements.each(function (nm) {
    this.element.getElements(nm).each(function(el) {
	if ($defined(el._HooTip)) el._HooTip.onBlur(true);
    })
    }.bind(this));
    return false;
}
});

Element.implement( {
	HooForm : function(options) {
		return this._HooForm = new HooForm(this, options);
	}
});

HooForm.implement(new Events);